1、ioctl 的作用
	有些设备除了正常的读写操作外还有许多其他的特殊操作，这些特殊操作可以通过 ioctl 实现
2、应用层的 ioctl
	应用层的 ioctl 如下：
	fd：文件描述符
	request：请求码
	第3个参数是可选的，其含义由驱动决定
	int ioctl(int fd, unsigned long request, ...);
3、驱动层的 ioctl
	驱动层有两个 ioctl 函数，分别是 unlocked_ioctl 和 compat_ioctl ，这两个函数功能一样，只不过 compat_ioctl
用于64位系统执行32位应用的情况，它们的原型如下：
	file：文件句柄，为应用层 ioctl 的 fd 所关联的文件句柄
	request：请求码，与应用层 ioctl 的request 对应
	arg：控制参数，与应用层ioctl的第3个参数对应
	long (*unlocked_ioctl) (struct file *file, unsigned int request, unsigned long arg);
	long (*compat_ioctl) (struct file *file, unsigned int request, unsigned long arg);
4、请求码
	ioctl 的请求码有特定的格式，从高到低依次是8位设备类型、8位命令码、3位数据传输方向、13位数据传输大小，可以
通过宏定义生成，如下是生成控制命令的宏定义
	_IO(type, nr)			//生成普通的请求码，type 设备类型，nr 控制命令
	_IOR(type, nr, size)	//生成一条要读数据的请求码，size 为读取的字节数，给数据类型或变量即可，宏定义通过
							//sizeof计算其大小
	_IOW(type, nr, size)	//生成一条要写数据的请求码，size 为写入的字节数
	_IOWR(type, nr, size)	//生成一条要读写数据的请求码，size 为读写的字节数
	另外可以通过下列宏定义从请求码中提取相应字段：
	_IOC_DIR(nr)	//获取数据传输方向，_IOC_NONE 不传输数据，_IOC_READ 从驱动读数据，_IOC_WRITE 写数据到驱动，
					//_IOC_READ|_IOC_WRITE 双向
	_IOC_TYPE(nr)	//获取设备类型
	_IOC_NR(nr)		//获取控制命令
	_IOC_SIZE(nr)	//获取数据传输大小
5、内核已占用的请求码
	下列请求码内核已经占用，驱动中不可再次使用：
	FIOCLEX			_IO('f', 1)
	FIONCLEX		_IO('f', 2)
	FIONBIO			_IOW('f', 126, int)
	FIOASYNC		_IOW('f', 125, int)
	FIOQSIZE		_IOR('f', 128, loff_t)
	FIFREEZE		_IOWR('X', 119, int)
	FITHAW			_IOWR('X', 120, int)
	FS_IOC_FIEMAP	_IOWR('f', 11, struct fiemap)
	FIGETBSZ		_IO(0x00,2)
6、lseek 的作用
	文件句柄中有一个叫 loff_t f_pos 的成员，用于记录当前读写位置，他会随着 read 和 write 操作不断递增，lseek
函数的作用则是用来重新设置 loff_t f_pos 成员的值，使得应用层可以从指定偏移位置开始读写。
7、应用层的 lseek
	应用层 lseek 如下：
	fd：文件描述符
	offset：偏移量
	whence：相对位置，SEEK_SET 相对于文件开始，SEEK_CUR 相对于当前位置，SEEK_END 相对于文件结尾
	off_t lseek(int fd, off_t offset, int whence);
8、驱动层的 lseek
	驱动层 lseek 如下：
	file：文件句柄，为应用层 lseek 的 fd 所关联的文件句柄
	offset：偏移量，与应用层的 offset 对应
	whence：相对位置，与应用层的 whence 对应
	loff_t (*llseek) (struct file *file, loff_t offset, int whence);
	